<template>
  <div class="tem-table">
    <CHeader :keyword="keyword" @onKeywordChange="onKeywordChange" @onClearKeyword="onClearKeyword" @onSearch="onSearch"
             @onReset="onReset"
             @onNew="onNew"/>
    <div class="tem-table-box">
      <el-table v-loading="loading" height="100%" :data="tableData" border style="width: 100%">
        <el-table-column prop="id" label="角色ID" min-width="200"/>
        <el-table-column prop="roleName" label="角色名称" min-width="200"/>
        <el-table-column label="是否管理员" min-width="140">
          <template #default="{row}">
            <el-tag :type="row.isAdmin?'success':'primary'">{{ row.isAdmin ? '管理员' : '普通用户' }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="权限等级" min-width="140">
          <template #default="{row}">
            {{ getRole(row.roleLevel) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" min-width="180">
          <template #default="{ row }">
            <el-button link type="primary"
                       size="small" @click="onNew(row)">编辑
            </el-button>
            <el-button link type="danger"
                       size="small" @click="onDel(row.id)">删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <div style="display: flex; justify-content: flex-end; padding: 10px;">
      <el-pagination
          v-model:current-page="pageNo"
          v-model:page-size="pageSize"
          :page-sizes="[10, 20, 30, 50]"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          background
          @size-change="handleSizeChange"
          @current-change="handleNoChange"
      />
    </div>
    <el-dialog width="500px" v-model="dialogTableVisible" :title="title? '编辑角色':'创建角色'">
      <el-form :rules="rules" ref="formRef" :model="submitForm" label-width="100px">
        <el-form-item label="角色名称" prop="roleName">
          <el-input placeholder="输入角色名称" style="width: 100%;" v-model.number="submitForm.roleName"></el-input>
        </el-form-item>
        <el-form-item label="是否管理员" prop="isAdmin">
          <el-select placeholder="选择是否管理员" style="width: 100%;" v-model="submitForm.isAdmin">
            <el-option :value="true" label="管理员"></el-option>
            <el-option :value="false" label="普通用户"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="角色等级" prop="roleLevel">
          <el-select placeholder="选择角色等级" style="width: 100%;" v-model="submitForm.roleLevel">
            <el-option :value="10" label="可读可写"></el-option>
            <el-option :value="1" label="只读权限"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="菜单权限">
          <el-tree-select
              ref="menuSelect"
              style="width: 100%;"
              placeholder="请选择菜单权限"
              v-model="submitForm.ids"
              clearable
              @check="onCheck"
              node-key="id"
              :props="{label: 'symbolStr'}"
              multiple
              :data="permStrData"
              :render-content="renderTreeContent"
              :render-after-expand="false"
              show-checkbox
              check-strictly
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogTableVisible = false">取 消</el-button>
        <el-button type="primary" @click="newRole(formRef)">提 交</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import {onBeforeMount} from "vue";
import type {FormInstance} from 'element-plus';
import {
  ElMessage,
  ElMessageBox, ElTree,
} from 'element-plus';

import CHeader from '@/components/CHeader.vue';
import getRole from '@/utils/getRoleName';
import {
  delAppRole,
  editAppRole,
  EditAppRoleArgs,
  getAppRoleList, getPermStrTreeData, getRoleSelectedMenuNodeIds, getRoleSelectedPermStr
} from "@/service/AppManager";
import type {AppRoleMo} from "@/service/entity/AppRoleMo";
import {PermStrDao} from "@/service/entity/PermStrDao";

const props = defineProps<{
  appId: any
}>()

onBeforeMount(async () => {
  updata()
  const data = await getPermStrTreeData(props.appId)
  const arr = data.arr
  dealTreeData(arr, 0)
  permStrData.value = arr
})

const dealTreeData = (arr: PermStrDao[], index) => {
  if (arr && arr.length) {
    for (let item of arr) {
      index++
      if (item.title) {
        item.symbolStr = `${index}、${item.title}[${item.symbolStr}]`
      } else {
        item.symbolStr = `${index}、${item.symbolStr}`
      }
      if (item.children) {
        dealTreeData(item.children, index * 10)
      }
    }
  }
}

const onCheck = (data) => {
  let arr = new Set(submitForm.ids)
  const checked = arr.has(data.id)
  if (checked) {
    arr.add(data.id)
  } else {
    arr.delete(data.id)
  }
  cascadeParent(data.parentId, checked, arr)
  cascadeChildren(data.children, checked, arr)
  submitForm.ids = [...arr]
}

const cascadeParent = (parentId,checked, arr) => {
  const parentNode = menuSelect.value.getNode(parentId)
  if (!parentNode) {
    return
  }
  if (checked){
    arr.add(parentId)
  } else {
    const pc = parentNode.data.children
    let ok = false
    for (let item of pc) {
      if (arr.has(item.id)) {
        ok = true
        break
      }
    }
    if (!ok) {
      arr.delete(parentId)
    }
  }
  cascadeParent(parentNode.data.parentId, checked, arr)
}

const cascadeChildren = (children, checked, arr) => {
  if (!children || !children.length) {
    return
  }
  if (checked) {
    for (let item of children) {
      arr.add(item.id)
      cascadeChildren(item.children, checked, arr)
    }
  } else {
    for (let item of children) {
      arr.delete(item.id)
      cascadeChildren(item.children, checked, arr)
    }
  }
}

const menuSelect = ref<InstanceType<typeof ElTree>>()
const permStrData = ref<PermStrDao[]>([])
const total = ref(0)
const pageNo = ref(1)
const pageSize = ref(10)
const keyword = ref('')
const tableData = ref([])
const loading = ref(false)
let title = ref(false)
let dialogTableVisible = ref(false)

const submitForm = reactive<EditAppRoleArgs>({
  appId: '',
  roleId: undefined,
  roleLevel: 10,
  roleName: '',
  isAdmin: false,
  ids: []
})
const formRef = ref<FormInstance>()
const rules = reactive({
  roleLevel: [
    {required: true, message: '权限必选', trigger: 'change'},
  ],
  roleName: [{
    required: true, message: '角色名称必填', trigger: 'blur'
  }]
})

const renderTreeContent = (h, {data}) => {
  return h(
      'span',
      {
        style: {
          style: {color: 'black'}
        },
      },
      data.symbolStr
  )
}

const onKeywordChange = (val: string) => {
  keyword.value = val
  updata()
}

const onClearKeyword = () => {
  keyword.value = ''
  updata()
}

const onSearch = async () => {
  updata()
}

const onReset = async () => {
  keyword.value = ''
  pageNo.value = 1
  pageSize.value = 10
  updata()
}


const onNew = async (row?: AppRoleMo) => {
  if (row) {

    for (let key in row) {
      submitForm[key] = row[key]
    }
    submitForm['roleId'] = row.id
    const ids = []
    const resRoleSelectedPermStr = await getRoleSelectedPermStr(props.appId, row.id)
    if (resRoleSelectedPermStr) {
      ids.push(...resRoleSelectedPermStr.arr)
    }
    const roleSelectedMenuNodeIds = await getRoleSelectedMenuNodeIds(row.id);
    if (roleSelectedMenuNodeIds) {
      ids.push(...roleSelectedMenuNodeIds.arr)
    }
    submitForm.ids = ids
    title.value = true
  } else {
    title.value = false
    submitForm['appId'] = props.appId
    submitForm['roleId'] = undefined
    submitForm['roleLevel'] = 10
    submitForm['roleName'] = ''
    submitForm['isAdmin'] = false
    submitForm['ids'] = []
  }
  dialogTableVisible.value = true
}
const newRole = async (formRef: FormInstance | undefined) => {
  if (!formRef) {
    return
  }
  await formRef.validate(async (valid, fields) => {
    if (valid) {
      const res = await editAppRole({...submitForm, ids: menuSelect.value.getCheckedKeys()})
      if (!res) return false
      dialogTableVisible.value = false
      formRef.resetFields()
      updata()
      ElMessage({
        type: 'success',
        message: '已提交'
      })
      return true
    } else {
      return false
    }
  })
}

const onDel = (id) => {
  ElMessageBox.confirm(
      '永久删除该条信息. 是否确认?',
      'Warning',
      {
        confirmButtonText: '确认',
        cancelButtonText: '取消',
        type: 'warning',
      }
  )
      .then(async () => {
        const res = await delAppRole(id)
        if (res) {
          updata()
        }
      })
      .catch(() => {
        ElMessage({
          type: 'info',
          message: '取消删除',
        })
      })

}

async function updata() {
  loading.value = true
  try {
    const res = await getAppRoleList({
      appId: props.appId,
      pageNo: pageNo.value,
      pageSize: pageSize.value,
      keyword: keyword.value
    })
    tableData.value = res.arr
    total.value = res.total
  } finally {
    setTimeout(() => loading.value = false, 200)
  }
}

const handleSizeChange = (val) => {
  pageSize.value = val
  updata()
}
const handleNoChange = (val) => {
  pageNo.value = val
  updata()
}

</script>

<style scoped lang="scss">
@import "@/global.scss";

.tem-table {
  height: 100%;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  padding: 10px;
}


.tem-table-box {
  flex: 1;
  overflow: hidden;
}
</style>